import { Graph } from '@antv/x6';

/**
 * x6实例化
 */
export function initGraph(id = 'container', opt = {}) {
  const graph = new Graph({
    container: document.getElementById(id),
    width: opt.width || '100%',
    height: opt.height || '100%',
    // 监听容器大小改变，并自动更新画布大小
    // https://x6.antv.vision/zh/docs/api/graph/graph#autoresize
    autoResize: false,
    // 网格
    grid: {
      size: 10, // 网格大小 10px
      visible: false, // 渲染网格背景
      type: 'mesh',
      args: {
        color: '#D0D0D0',
        thickness: 1, // 网格线宽度/网格点大小
        factor: 10
      }
    },
    tools: [{ name: 'vertices' }],
    // 可以通过 highlighting 选项来指定触发某种交互时的高亮样式
    // https://x6.antv.vision/zh/docs/api/graph/interaction/#highlighting
    highlighting: {
      // 当链接桩可以被链接时，在链接桩外围渲染一个 2px 宽的红色矩形框
      magnetAvailable: {
        name: 'stroke',
        args: {
          padding: 4,
          attrs: {
            'stroke-width': 4,
            stroke: 'skyblue'
          }
        }
      },
      // 连线过程中，自动吸附到链接桩时被使用
      magnetAdsorbed: {
        name: 'stroke',
        args: {
          padding: 4,
          attrs: {
            'stroke-width': 8,
            stroke: 'skyblue'
          }
        }
      }
    },
    // 滚轮缩放
    mousewheel: {
      enabled: true,
      modifiers: ['ctrl', 'meta']
    },
    // 定制节点和边的交互行为
    // https://x6.antv.vision/zh/docs/tutorial/basic/interacting/#%E5%AE%9A%E5%88%B6%E4%BA%A4%E4%BA%92%E8%A1%8C%E4%B8%BA
    interacting(cellView) {
      if (cellView.cell.getData()?.disableMove) {
        return { nodeMovable: false };
      }
      return true;
    },
    // 配置全局的连线规则
    // https://x6.antv.vision/zh/docs/api/graph/interaction
    connecting: {
      // 自动吸附 最大距离50
      snap: { radius: 50 },
      // 不允许连接到画布空白位置的点
      allowBlank: false,
      // 允许创建循环连线
      allowLoop: false,
      // 不允许在相同的起始节点和终止之间创建多条边
      allowMulti: false,
      // 高亮显示所有可用的连接桩或节点
      // https://x6.antv.vision/zh/docs/tutorial/basic/interacting/#highlight
      highlight: true,
      // 当连接到节点时，通过 sourceAnchor 来指定源节点的锚点。
      sourceAnchor: { name: 'center' },
      // 当连接到节点时，通过 targetAnchor 来指定目标节点的锚点。
      targetAnchor: { name: 'center' },
      // 指定连接点，默认值为 boundary。
      // connectionPoint: 'boundary',
      connectionPoint: {
        name: 'boundary',
        args: {
          sticky: true
        }
      },
      // 连接器将起点、路由返回的点、终点加工为 元素的 d 属性，决定了边渲染到画布后的样式，默认值为 normal。
      connector: {
        name: 'rounded',
        args: { radius: 4 }
      },
      // 路由将边的路径点 vertices 做进一步转换处理，并在必要时添加额外的点，然后返回处理后的点，默认值为 normal。
      router: {
        name: 'orth',
        args: { padding: 10 }
      },
      // https://x6.antv.vision/zh/docs/tutorial/basic/interacting/#validatemagnet
      // 判断是否新增边
      validateMagnet() {
        // const portGroup = magnet.getAttribute('port-group');
        // return portGroup !== 'in';
        return true;
      },
      // 连接的过程中创建新的边
      createEdge() {
        return this.createEdge({
          zIndex: -1,
          attrs: {
            line: {
              // strokeDasharray: "5 5",
              stroke: '#606C80',
              strokeWidth: 1.5,
              targetMarker: {
                name: 'block',
                args: { size: '6' }
              },
              strokeDasharray: 0, // 虚线
              style: { animation: 'ant-line 30s infinite linear' }
            }
          }
        });
      },
      // https://x6.antv.vision/zh/docs/tutorial/basic/interacting/#validateconnection
      // 在移动边的时候判断连接是否有效，如果返回 false，当鼠标放开的时候，不会连接到当前元素，否则会连接到当前元素。
      // 1、节点不能自己连接自己 (\.)
      // 2、结束节点不能连接其他节点 (\.)
      // 3、开始节点不能被其他节点连接 (\.)
      // 4、开始节点只能有一条出线，且只能连接人工节点 (\.)
      // 5、画布只能包含一个开始节点 (NodesBar.vue)
      // 保存前校验
      // 1、不能存在孤立节点，就是没有连接其他节点，也没有被连接的节点 (\common\index.js)
      // 2、画布至少包含 一个开始节点、一个人工节点、一个结束节点 (\common\index.js)
      validateConnection({ targetView, targetMagnet, sourceCell, targetCell }) {
        if (!targetMagnet) {
          return false;
        }

        // 判断节点类型是否可连接
        // 结束节点不能作为起始节点
        if (sourceCell.shape === 'end') return false;

        // 开始节点不能作为目标节点
        if (targetCell.shape === 'start') return false;

        // 文本节点不进行连线
        if (sourceCell.shape === 'text') return false;
        if (targetCell.shape === 'text') return false;

        if (sourceCell.getData()?.disableMove) return false;
        // 判断目标链接桩是否可连接
        const portId = targetMagnet.getAttribute('port');
        const node = targetView.cell;
        const port = node.getPort(portId);
        if (!port) {
          return false;
        }

        return true;
      }
    },
    scaling: {
      min: 0.05, // 默认值为 0.01
      max: 12 // 默认值为 16
    },
    ...opt
  });
  return graph;
}
